package com.zl.gmadmin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zl.gmadmin.entity.SysMenu;
import com.zl.gmadmin.entity.SysRole;
import com.zl.gmadmin.mapper.SysMenuMapper;
import com.zl.gmadmin.service.SysMenuService;
import com.zl.gmadmin.service.SysRoleService;
import com.zl.gmadmin.service.dto.MenuDto;
import com.zl.gmadmin.utils.FileUtil;
import com.zl.gmadmin.utils.JsonUtil;
import com.zl.gmadmin.utils.LogUtil;
import com.zl.gmadmin.vo.menu.MenuVo;
import com.zl.gmadmin.vo.menu.SysMenuVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhangliang
 * @version 1.0
 * @date 2021/2/2 16:03
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {


    private final SysMenuMapper sysMenuMapper;

    private final SysRoleService sysRoleService;

    public SysMenuServiceImpl(SysMenuMapper sysMenuMapper, SysRoleService sysRoleService) {
        this.sysMenuMapper = sysMenuMapper;
        this.sysRoleService = sysRoleService;
    }

    @Override
    public List<SysMenu> selectByRoleIdList(Set<Long> ids) {
        return sysMenuMapper.selectByRoleIdList(ids);
    }

    @Override
    public List<MenuVo> findMenuByUserId(Long currentUserId) {
        List<SysRole> sysRoles = sysRoleService.selectByUserId(currentUserId);
        Set<Long> ids = sysRoles.stream().map(SysRole::getId).collect(Collectors.toSet());
        List<SysMenu> sysMenus = selectByRoleIdList(ids).stream().filter(sysMenu -> sysMenu.getType() != 2).collect(Collectors.toList());

        //封装菜单
        List<com.zl.gmadmin.service.dto.MenuDto> menuDtoList = sysMenus.stream().map(MenuDto::buildMenuDto).collect(Collectors.toList());
        //查找树形菜单


        //构建菜单树
        LinkedList<MenuVo> menuVos = new LinkedList<>(buildTree(menuDtoList).stream().map(MenuVo::buildMenu).collect(Collectors.toList()));

        return menuVos;
    }

    @Override
    public List<MenuDto> buildTree(List<MenuDto> menuDtoList) {
        List<MenuDto> trees = new ArrayList<>();
        Set<Long> ids = new HashSet<>();

        for (MenuDto menuDto : menuDtoList) {
            if (menuDto.getPid() == null) {
                trees.add(menuDto);
            }
            //查找子菜单
            for (MenuDto item : menuDtoList) {
                if (menuDto.getId().equals(item.getPid())) {
                    if (menuDto.getChildren() == null) {
                        menuDto.setChildren(new ArrayList<>());
                    }
                    menuDto.getChildren().add(item);
                    ids.add(item.getId());
                }
            }
        }

        if (trees.size() == 0) {
            trees = menuDtoList.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList());
        }
        return trees;
    }

    @Override
    public List<SysMenuVo> queryMenu() {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();

        List<SysMenu> sysMenus = sysMenuMapper.selectList(queryWrapper).stream().filter((sysMenu -> sysMenu.getType()!=2)).collect(Collectors.toList());
        List<MenuDto> menuDtoList = sysMenus.stream().map(MenuDto::buildMenuDto).collect(Collectors.toList());

        //构建菜单树
        LinkedList<MenuDto> menuDtoLinkedList = new LinkedList<>(buildTree(menuDtoList));

        LogUtil.debug("构建菜单");
        LogUtil.debug(JsonUtil.toJsonStr(menuDtoLinkedList));

        SysMenuVo sysMenuVo = new SysMenuVo();
        List<SysMenuVo> sysMenuVoList = menuDtoLinkedList.stream().map(sysMenuVo::buildMenu).collect(Collectors.toList());

        //返回数据封装
        LogUtil.debug("构建菜单最终结果");
        LogUtil.debug(JsonUtil.toJsonStr(sysMenuVoList));
        return sysMenuVoList;
    }

    @Override
    public List<SysMenuVo> querySupMenu(Long pid) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(pid)) {
            queryWrapper.eq("pid", pid);
        } else {
            queryWrapper.isNull("pid");
        }
        List<SysMenu> sysMenus = sysMenuMapper.selectList(queryWrapper);
        List<MenuDto> menuDtoList = sysMenus.stream().map(MenuDto::buildMenuDto).collect(Collectors.toList());

        SysMenuVo sysMenuVo = new SysMenuVo();
        List<SysMenuVo> sysMenuVos = menuDtoList.stream().map(sysMenuVo::buildMenu).collect(Collectors.toList());

        LogUtil.debug("懒加载菜单最终结果");
        LogUtil.debug(JsonUtil.toJsonStr(sysMenuVos));

        return sysMenuVos;
    }

    @Override
    public Long queryMenuSort(String sort) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("menu_sort");
        queryWrapper.last("limit 1");

        Long menuSort = sysMenuMapper.selectOne(queryWrapper).getMenuSort();

        return menuSort;
    }

    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        List<SysMenu> sysMenus = sysMenuMapper.selectBatchIds(idList);
        sysMenuMapper.deleteBatchIds(idList);

        for (SysMenu menu : sysMenus
        ) {
            if (Objects.nonNull(menu.getPid())){
                QueryWrapper<SysMenu> sysMenuQueryWrapper=new QueryWrapper<>();
                sysMenuQueryWrapper.eq("menu_id",menu.getPid());
                SysMenu sysMenu=sysMenuMapper.selectById(menu.getPid());
                sysMenu.setSubCount(sysMenu.getSubCount()-1);
                sysMenuMapper.update(sysMenu,sysMenuQueryWrapper);
            }
        }

        // 还要删除相关联角色表
        sysMenuMapper.deleteConnectedRoles(idList);
        return true;
    }

    @Override
    public void download(HttpServletResponse response, List<Long> ids) throws IOException {
        List<SysMenu> menus = sysMenuMapper.selectBatchIds(ids);


        List<Map<String, Object>> mapList = new ArrayList<>();
        for (SysMenu menu : menus) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", menu.getId());
            map.put("父级菜单pid", menu.getPid());
            map.put("子菜单总数", menu.getSubCount());
            map.put("类型", menu.getType());
            map.put("标题", menu.getTitle());
            map.put("姓名", menu.getName());
            map.put("组件", menu.getComponent());
            map.put("排序", menu.getMenuSort());
            map.put("图标名称", menu.getIcon());
            map.put("图标地址", menu.getPath());
            map.put("外链", menu.getiFrame());
            map.put("缓存", menu.getCache());
            map.put("隐藏", menu.getHidden());
            map.put("权限标识", menu.getComponent());
            map.put("创建于", menu.getCreateBy());
            map.put("创建时间", menu.getCreateTime());
            map.put("更新于", menu.getUpdateBy());
            map.put("更新时间", menu.getUpdateTime());
            mapList.add(map);
        }


        FileUtil.downloadExcel(mapList, response);
    }

    @Override
    public void addMenu(SysMenu sysMenu) {
        sysMenuMapper.insert(sysMenu);
        if (Objects.nonNull(sysMenu.getPid())) {
            QueryWrapper<SysMenu> queryWrapper=new QueryWrapper<>();
            queryWrapper.eq("menu_id",sysMenu.getPid());
            SysMenu s = sysMenuMapper.selectById(sysMenu.getPid());
            s.setSubCount(s.getSubCount() + 1);
            sysMenuMapper.update(s, queryWrapper);
        }
    }
}
